using System;
using System.Collections.Generic;
using System.Linq;

namespace Utility.GameEvents.Core {
    public static class EventBus
    {
        private static readonly Dictionary<Type, List<object>> m_listeners = new();

        public static void Register<T>(IGameEventListener<T> listener) where T : IGameEvent
        {
            var type = typeof(T);
            if (!m_listeners.ContainsKey(type))
                m_listeners[type] = new List<object>();
            if (!m_listeners[type].Contains(listener)) // Optional: Prevent double registration
                m_listeners[type].Add(listener);
        }

        public static void Unregister<T>(IGameEventListener<T> listener) where T : IGameEvent
        {
            var type = typeof(T);
            if (m_listeners.TryGetValue(type, out var list))
                list.Remove(listener);
        }

        public static void Raise<T>(T gameEvent) where T : IGameEvent
        {
            var type = typeof(T);
            if (m_listeners.TryGetValue(type, out var list))
            {
                // Iterate backwards if listeners might unregister themselves during OnEventRaised
                for (int i = list.Count - 1; i >= 0; i--) {
                    if (list[i] is IGameEventListener<T> typedListener) {
                        typedListener.OnEventRaised(gameEvent);
                    }
                }
                
                // Original: foreach (var listener in list.Cast<IGameEventListener<T>>())
                //              listener.OnEventRaised(gameEvent);
                // Backward iteration is safer if a listener unregisters itself or another listener for the same event.
                // The .Cast<>() creates a new collection, so modifications to the original list during iteration are less problematic with it,
                // but direct backward iteration on the original list is a common robust pattern.
            }
        }
    }
}